package com.taotao.tools.validate.validator;

import com.taotao.tools.core.str.StringUtil;
import com.taotao.tools.validate.annotations.NoRepeat;
import lombok.extern.slf4j.Slf4j;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;


@Slf4j
public class NoRepeatValidator implements ConstraintValidator<NoRepeat, Object> {

    private NoRepeat anno;

    @Override
    public void initialize(NoRepeat anno) {
        this.anno = anno;
    }

    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {
        if (!(value instanceof Collection) && !value.getClass().isArray()) {
            throw new IllegalStateException("@NoRepeat 注解不能用在非Collection类型或数组的属性上");
        }


        List collection = null;
        if (value.getClass().isArray()) {
            collection = Arrays.asList((Object[]) value);
        } else {
            collection = new ArrayList<>((Collection) value);
        }

        boolean validField = !StringUtil.isBlank(anno.targetField());
        Set<Object> list = new HashSet<>(collection.size());
        for (Object obj : collection) {
            Object v = obj;
            if (validField) {
                v = getFieldValue(obj, anno.targetField());
            }


            if (list.contains(v)) {
                if (StringUtil.isBlank(anno.message())) {
                    //重写错误提示
                    context.disableDefaultConstraintViolation();
                    context.buildConstraintViolationWithTemplate(anno.tipName() + "存在重复数据").addConstraintViolation();
                }
                return false;
            }

            list.add(v);
        }


        return true;
    }

    private Object getFieldValue(Object obj, String targetField) {
        try {
            Field field = obj.getClass().getDeclaredField(targetField);
            field.setAccessible(true);
            return field.get(obj);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            log.error("", e);
        }

        return null;
    }


}
